home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / irit / freefrm1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  53.1 KB  |  1,241 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to provide the required interfact for the cagd library for the    *
  7. * free form surfaces and curves.                         *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include "program.h"
  13. #include "allocate.h"
  14. #include "attribut.h"
  15. #include "objects.h"
  16. #include "primitiv.h"
  17. #include "windows.h"
  18. #include "ip_cnvrt.h"
  19. #include "freeform.h"
  20.  
  21. static IPObjectStruct *GetControlMesh(IPObjectStruct *LstObjList,
  22.                       int UOrder,
  23.                       int VOrder,
  24.                       CagdGeomType GType,
  25.                       char **ErrStr);
  26. static IPObjectStruct *GetControlPoly(IPObjectStruct *PtObjList,
  27.                       int Order,
  28.                       CagdGeomType GType,
  29.                       char **ErrStr);
  30.  
  31. /*****************************************************************************
  32. * DESCRIPTION:                                                               M
  33. * Routine to fetch the boolean object DrawCtlPt.                 M
  34. *                                                                            *
  35. * PARAMETERS:                                                                M
  36. *   None                                                                     M
  37. *                                                                            *
  38. * RETURN VALUE:                                                              M
  39. *   int:        Value of DrawCtlPt object.                                   M
  40. *                                                                            *
  41. * KEYWORDS:                                                                  M
  42. *   GetDrawCtlPt                                                             M
  43. *****************************************************************************/
  44. int GetDrawCtlPt(void)
  45. {
  46.     int DrawCtlPt;
  47.     IPObjectStruct
  48.     *PObj = GetObject("DRAWCTLPT");
  49.  
  50.     if (PObj == NULL || !IP_IS_NUM_OBJ(PObj)) {
  51.     IritPrsrFatalError("No numeric object name DRAWCTLPT is defined");
  52.     DrawCtlPt = 0;
  53.     }
  54.     else
  55.     DrawCtlPt = REAL_TO_INT(PObj -> U.R);
  56.  
  57.     return DrawCtlPt;
  58. }
  59.  
  60. /*****************************************************************************
  61. * DESCRIPTION:                                                               M
  62. * Routine to fetch the boolean object FourPerFlat.                 M
  63. *                                                                            *
  64. * PARAMETERS:                                                                M
  65. *   None                                                                     M
  66. *                                                                            *
  67. * RETURN VALUE:                                                              M
  68. *   int:        Value of Flat4Ply object.                                    M
  69. *                                                                            *
  70. * KEYWORDS:                                                                  M
  71. *   GetFourPerFlat                                                           M
  72. *****************************************************************************/
  73. int GetFourPerFlat(void)
  74. {
  75.     int FourPerFlat;
  76.     IPObjectStruct
  77.     *PObj = GetObject("FLAT4PLY");
  78.  
  79.     if (PObj == NULL || !IP_IS_NUM_OBJ(PObj)) {
  80.     IritPrsrFatalError("No numeric object name FLAT4PLY is defined");
  81.     FourPerFlat = 0;
  82.     }
  83.     else
  84.     FourPerFlat = REAL_TO_INT(PObj -> U.R);
  85.  
  86.     return FourPerFlat;
  87. }
  88.  
  89. /*****************************************************************************
  90. * DESCRIPTION:                                                               M
  91. * Routine to fetch the boolean object Poly_Approx_opt.                 M
  92. *                                                                            *
  93. * PARAMETERS:                                                                M
  94. *   None                                                                     M
  95. *                                                                            *
  96. * RETURN VALUE:                                                              M
  97. *   int:        Value of Poly_Approx_opt object.                             M
  98. *                                                                            *
  99. * KEYWORDS:                                                                  M
  100. *   GetPolyApproxOptimal                                                     M
  101. *****************************************************************************/
  102. int GetPolyApproxOptimal(void)
  103. {
  104.     int PolyApproxOpt;
  105.     IPObjectStruct
  106.     *PObj = GetObject("POLY_APPROX_OPT");
  107.  
  108.     if (PObj == NULL || !IP_IS_NUM_OBJ(PObj)) {
  109.     IritPrsrFatalError("No numeric object name POLY_APPROX_OPT is defined");
  110.     PolyApproxOpt = 0;
  111.     }
  112.     else
  113.     PolyApproxOpt = REAL_TO_INT(PObj -> U.R);
  114.  
  115.     return PolyApproxOpt;
  116. }
  117.  
  118. /*****************************************************************************
  119. * DESCRIPTION:                                                               M
  120. * Routine to fetch the boolean object Poly_Approx_Uv.                 M
  121. *                                                                            *
  122. * PARAMETERS:                                                                M
  123. *   None                                                                     M
  124. *                                                                            *
  125. * RETURN VALUE:                                                              M
  126. *   int:        Value of Poly_Approx_Uv object.                              M
  127. *                                                                            *
  128. * KEYWORDS:                                                                  M
  129. *   GetPolyApproxUV                                                          M
  130. *****************************************************************************/
  131. int GetPolyApproxUV(void)
  132. {
  133.     int PolyApproxUV;
  134.     IPObjectStruct
  135.     *PObj = GetObject("POLY_APPROX_UV");
  136.  
  137.     if (PObj == NULL || !IP_IS_NUM_OBJ(PObj)) {
  138.     IritPrsrFatalError("No numeric object name POLY_APPROX_UV is defined");
  139.     PolyApproxUV = 0;
  140.     }
  141.     else
  142.     PolyApproxUV = REAL_TO_INT(PObj -> U.R);
  143.  
  144.     return PolyApproxUV;
  145. }
  146.  
  147. /*****************************************************************************
  148. * DESCRIPTION:                                                               M
  149. * Routine to fetch the boolean object Poly_Approx_Tol.                 M
  150. *                                                                            *
  151. * PARAMETERS:                                                                M
  152. *   None                                                                     M
  153. *                                                                            *
  154. * RETURN VALUE:                                                              M
  155. *   int:        Value of Poly_Approx_Tol object.                             M
  156. *                                                                            *
  157. * KEYWORDS:                                                                  M
  158. *   GetPolyApproxTol                                                         M
  159. *****************************************************************************/
  160. RealType GetPolyApproxTol(void)
  161. {
  162.     RealType PolyApproxTol;
  163.     IPObjectStruct
  164.     *PObj = GetObject("POLY_APPROX_TOL");
  165.  
  166.     if (PObj == NULL || !IP_IS_NUM_OBJ(PObj)) {
  167.     IritPrsrFatalError("No numeric object name POLY_APPROX_TOL is defined");
  168.     PolyApproxTol = 0.1;
  169.     }
  170.     else
  171.     PolyApproxTol = PObj -> U.R;
  172.  
  173.     return PolyApproxTol;
  174. }
  175.  
  176. /*****************************************************************************
  177. * DESCRIPTION:                                                               *
  178. * Routine to copy the control mesh lists to a surface control mesh.          *
  179. *   The surface is allocated here as well.                     *
  180. *   Returns the surface if o.k., otherwise NULL.                 *
  181. *                                                                            *
  182. * PARAMETERS:                                                                *
  183. *   LstObjList: A list object of lists of control points.                    *
  184. *   UOrder:     U order of surface.                                          *
  185. *   VOrder:     V order of surface.                                          *
  186. *   GType:      Geometry type - Bezier, Bspline etc.                         *
  187. *   ErrStr:     If an error, detected, this is initialized with description. *
  188. *                                                                            *
  189. * RETURN VALUE:                                                              *
  190. *   IPObjectStruct *:   A surface object if successful, NULL otherwise.      *
  191. *****************************************************************************/
  192. static IPObjectStruct *GetControlMesh(IPObjectStruct *LstObjList,
  193.                       int UOrder,
  194.                       int VOrder,
  195.                       CagdGeomType GType,
  196.                       char **ErrStr)
  197. {
  198.     int i, j, k, PtSize,
  199.     NumVertices = 0,
  200.     NumVerticesFirst = -1,
  201.         NumLists = 0;
  202.     CagdRType **r;
  203.     RealType *v;
  204.     IPObjectStruct *SrfObj, *LstObj, *PtObj;
  205.     CagdPointType
  206.     PtType = CAGD_PT_E1_TYPE;
  207.  
  208.     if (!IP_IS_OLST_OBJ(LstObjList))
  209.     IritFatalError("SURFACE: Not object list object!");
  210.  
  211.     while ((LstObj = ListObjectGet(LstObjList, NumLists)) != NULL) {
  212.     if (!IP_IS_OLST_OBJ(LstObj)) {
  213.         *ErrStr = "Non list object found in list";
  214.         return NULL;
  215.     }
  216.  
  217.         NumVertices = -1;
  218.         while ((PtObj = ListObjectGet(LstObj, ++NumVertices)) != NULL) {
  219.         if (!IP_IS_CTLPT_OBJ(PtObj) &&
  220.         !IP_IS_POINT_OBJ(PtObj) &&
  221.         !IP_IS_VEC_OBJ(PtObj)) {
  222.         *ErrStr = "Non point object found in list";
  223.         return NULL;
  224.         }
  225.     }
  226.     if ((PtType = IritPrsrCoerceCommonSpace(LstObj, PtType)) ==
  227.                                 CAGD_PT_NONE) {
  228.         *ErrStr = "";
  229.         return NULL;
  230.     }
  231.  
  232.     if (NumLists++ == 0)
  233.         NumVerticesFirst = NumVertices;
  234.         else if (NumVerticesFirst != NumVertices) {
  235.         *ErrStr = "Different size of point lists";
  236.         return NULL;
  237.     }
  238.     }
  239.  
  240.     /* Coerce all points to a common space, in place. */
  241.     while ((LstObj = ListObjectGet(LstObjList, NumLists)) != NULL)
  242.     if (IritPrsrCoercePtsListTo(LstObj, PtType) == CAGD_PT_NONE) {
  243.         *ErrStr = "";
  244.         return NULL;
  245.     }
  246.  
  247.     if (NumVertices < 2 || NumLists < 2) {
  248.     *ErrStr = "Less than 2 points in a row/col";
  249.     return NULL;
  250.     }
  251.  
  252.     SrfObj = GenSRFObject(NULL);
  253.     switch (GType) {
  254.     case CAGD_SBEZIER_TYPE:
  255.         SrfObj -> U.Srfs = BzrSrfNew(NumVertices, NumLists, PtType);
  256.         break;
  257.     case CAGD_SBSPLINE_TYPE:
  258.         SrfObj -> U.Srfs = BspSrfNew(NumVertices, NumLists,
  259.                      UOrder, VOrder, PtType);
  260.         break;
  261.     default:
  262.         break;
  263.     }
  264.     AttrSetObjectColor(SrfObj, GlblPrimColor);       /* Set its default color. */
  265.     PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
  266.  
  267.     for (r = SrfObj -> U.Srfs -> Points, i = 0; i < NumLists; i++) {
  268.     LstObj = ListObjectGet(LstObjList, i);
  269.  
  270.         for (j = 0; j < NumVertices; j++) {
  271.         IPObjectStruct
  272.         *VObj = ListObjectGet(LstObj, j);
  273.  
  274.         v = VObj -> U.CtlPt.Coords;
  275.  
  276.         if (CAGD_IS_RATIONAL_PT(PtType))
  277.         for (k = 0; k < PtSize; k++)
  278.             r[k][i * NumVertices + j] = *v++;
  279.         else
  280.         for (k = 1; k <= PtSize; k++)
  281.             r[k][i * NumVertices + j] = *++v;
  282.         }
  283.     }
  284.  
  285.     return SrfObj;
  286. }
  287.  
  288. /*****************************************************************************
  289. * DESCRIPTION:                                                               *
  290. * Routine to copy the control polygon to a curve's control polygon.          *
  291. *   The curve is allocated here as well.                     *
  292. *   Returns the surface if o.k., otherwise NULL.                 *
  293. *                                                                            *
  294. * PARAMETERS:                                                                *
  295. *   PtObjList:  A list object of control points.                          *
  296. *   Order:      Order of curve.                                             *
  297. *   GType:      Geometry type - Bezier, Bspline etc.                         *
  298. *   ErrStr:     If an error, detected, this is initialized with description. *
  299. *                                                                            *
  300. * RETURN VALUE:                                                              *
  301. *   IPObjectStruct *:   A curve object if successful, NULL otherwise.        *
  302. *****************************************************************************/
  303. static IPObjectStruct *GetControlPoly(IPObjectStruct *PtObjList,
  304.                       int Order,
  305.                       CagdGeomType GType,
  306.                       char **ErrStr)
  307. {
  308.     int i, j, PtSize,
  309.         NumVertices = -1;
  310.     CagdRType **r;
  311.     RealType *v;
  312.     IPObjectStruct *CrvObj, *PtObj;
  313.     CagdPointType PtType;
  314.  
  315.     *ErrStr = NULL;
  316.  
  317.     if (!IP_IS_OLST_OBJ(PtObjList))
  318.     IritFatalError("CURVE: Not object list object!");
  319.  
  320.     while ((PtObj = ListObjectGet(PtObjList, ++NumVertices)) != NULL) {
  321.     if (!IP_IS_CTLPT_OBJ(PtObj) &&
  322.         !IP_IS_POINT_OBJ(PtObj) &&
  323.         !IP_IS_VEC_OBJ(PtObj)) {
  324.         *ErrStr = "Non point object found in list";
  325.         return NULL;
  326.     }
  327.     }
  328.     
  329.     if (NumVertices < 2) {
  330.     *ErrStr = "Less than 2 points";
  331.     return NULL;
  332.     }
  333.  
  334.     /* Coerce all points to a common space, in place. */
  335.     if ((PtType = IritPrsrCoercePtsListTo(PtObjList, CAGD_PT_E1_TYPE))
  336.                             == CAGD_PT_NONE) {
  337.     *ErrStr = "";
  338.     return NULL;
  339.     }
  340.  
  341.     CrvObj = IPAllocObject("", IP_OBJ_CURVE, NULL);
  342.     switch (GType) {
  343.     case CAGD_CBEZIER_TYPE:
  344.         CrvObj -> U.Crvs = BzrCrvNew(NumVertices, PtType);
  345.         break;
  346.     case CAGD_CBSPLINE_TYPE:
  347.         CrvObj -> U.Crvs = BspCrvNew(NumVertices, Order, PtType);
  348.         break;
  349.     default:
  350.         break;
  351.     }
  352.     AttrSetObjectColor(CrvObj, GlblPrimColor);       /* Set its default color. */
  353.     PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
  354.  
  355.     for (r = CrvObj -> U.Crvs -> Points, i = 0; i < NumVertices; i++) {
  356.     IPObjectStruct
  357.         *VObj = ListObjectGet(PtObjList, i);
  358.  
  359.     v = VObj -> U.CtlPt.Coords;
  360.  
  361.     if (CAGD_IS_RATIONAL_PT(PtType))
  362.         for (j = 0; j < PtSize; j++)
  363.         r[j][i] = *v++;
  364.     else
  365.         for (j = 1; j <= PtSize; j++)
  366.         r[j][i] = *++v;
  367.     }
  368.  
  369.     return CrvObj;
  370. }
  371.  
  372. /*****************************************************************************
  373. * DESCRIPTION:                                                               *
  374. * Routine to copy the list of knots into the knot vector provided.           *
  375. *   Returns KnotVector if o.k., NULL otherwise (sets ErrStr to description). *
  376. *   Length can hold the requested length (in ctlpts) in case a uniform KV is *
  377. * requested. Length will return the actual length of the KV constructed.     *
  378. *                                                                            *
  379. * PARAMETERS:                                                                *
  380. *   KntObjList: A list of knots (numeric values).                            *
  381. *   Order:      Order of geometry to use this knot vector.                   *
  382. *   Length:     Expected length of knot vector.                              *
  383. *   ErrStr:     If an error, detected, this is initialized with description. *
  384. *                                                                            *
  385. * RETURN VALUE:                                                              *
  386. *   CagdRType *:   Allocated knot vector, or NULL if error.                  *
  387. *****************************************************************************/
  388. CagdRType *GetKnotVector(IPObjectStruct *KntObjList,
  389.              int Order,
  390.              int *Length,
  391.              char **ErrStr)
  392. {
  393.     int NumKnots = 0,
  394.     RequestLength = *Length;
  395.     CagdRType *KnotVector;
  396.     IPObjectStruct *KntObj;
  397.  
  398.     *ErrStr = NULL;
  399.  
  400.     if (!IP_IS_OLST_OBJ(KntObjList))
  401.     IritFatalError("KNOT: Not object list object!");
  402.  
  403.     *Length = ListObjectLength(KntObjList);
  404.     KnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) * *Length);
  405.  
  406.     while ((KntObj = ListObjectGet(KntObjList, NumKnots)) != NULL &&
  407.        NumKnots < *Length) {
  408.     if (!IP_IS_NUM_OBJ(KntObj)) {
  409.         *ErrStr = "Non numeric object found in list";
  410.         return NULL;
  411.     }
  412.  
  413.     KnotVector[NumKnots++] = KntObj -> U.R;
  414.     }
  415.  
  416.     if (NumKnots == 1 && KnotVector[0] < KV_MIN_LEGAL) {
  417.     int KVType = REAL_TO_INT(KnotVector[0]);
  418.  
  419.     IritFree((VoidPtr) KnotVector);
  420.  
  421.     *Length = RequestLength + Order;
  422.  
  423.     switch (KVType) {
  424.         case KV_UNIFORM_OPEN:
  425.         KnotVector = BspKnotUniformOpen(RequestLength, Order, NULL);
  426.         break;
  427.         case KV_UNIFORM_FLOAT:
  428.         KnotVector = BspKnotUniformFloat(RequestLength, Order, NULL);
  429.         break;
  430.         case KV_UNIFORM_PERIODIC:
  431.         KnotVector = BspKnotUniformPeriodic(RequestLength + Order - 1,
  432.                             Order, NULL);
  433.         *Length += Order - 1;
  434.         break;
  435.         default:
  436.         *ErrStr = "Invalid knot value";
  437.         fprintf(stderr,"Knot = %10.6g (%d)", KnotVector[0], KVType);
  438.         return NULL;
  439.     }
  440.     }
  441.     else if (NumKnots != *Length) {
  442.     *ErrStr = "Wrong knot vector length";
  443.     return NULL;
  444.     }
  445.  
  446.     return KnotVector;
  447. }
  448.  
  449. /*****************************************************************************
  450. * DESCRIPTION:                                                               M
  451. *   Routine to create a Bezier surface geometric object defined by a list of M
  452. * lists of vertices.                                 M
  453. *                                                                            *
  454. * PARAMETERS:                                                                M
  455. *   LstObjList: A list object of lists of control points.                    M
  456. *                                                                            *
  457. * RETURN VALUE:                                                              M
  458. *   IPObjectStruct *: A Bezier surface object if successful, NULL otherwise. M
  459. *                                                                            *
  460. * KEYWORDS:                                                                  M
  461. *   GenBezierSurfaceObject                                                   M
  462. *****************************************************************************/
  463. IPObjectStruct *GenBezierSurfaceObject(IPObjectStruct *LstObjList)
  464. {
  465.     char *ErrStr, Line[LINE_LEN];
  466.     IPObjectStruct
  467.     *SrfObj = GetControlMesh(LstObjList, -1, -1, CAGD_SBEZIER_TYPE, &ErrStr);
  468.  
  469.     if (SrfObj == NULL) {
  470.     sprintf(Line, "SBEZIER: %s, empty object result.\n", ErrStr);
  471.     IritPrsrFatalError(Line);
  472.     }
  473.  
  474.     return SrfObj;
  475. }
  476.  
  477. /*****************************************************************************
  478. * DESCRIPTION:                                                               M
  479. *   Routine to create a Bezier curve geometric object defined by a list of   M
  480. * vertices.                                     M
  481. *                                                                            *
  482. * PARAMETERS:                                                                M
  483. *   PtObjList:  A list object of control points.                          M
  484. *                                                                            *
  485. * RETURN VALUE:                                                              M
  486. *   IPObjectStruct *: A Bezier curve object if successful, NULL otherwise.   M
  487. *                                                                            *
  488. * KEYWORDS:                                                                  M
  489. *   GenBezierCurveObject                                                     M
  490. *****************************************************************************/
  491. IPObjectStruct *GenBezierCurveObject(IPObjectStruct *PtObjList)
  492. {
  493.     char *ErrStr, Line[LINE_LEN];
  494.     IPObjectStruct
  495.     *CrvObj = GetControlPoly(PtObjList, -1, CAGD_CBEZIER_TYPE, &ErrStr);
  496.  
  497.     if (CrvObj == NULL) {
  498.     sprintf(Line, "CBEZIER: %s\n, empty object result.", ErrStr);
  499.     IritPrsrFatalError(Line);
  500.     }
  501.  
  502.     return CrvObj;
  503. }
  504.  
  505. /*****************************************************************************
  506. * DESCRIPTION:                                                               M
  507. *   Routine to create a Bspline surface geometric object defined by a list   M
  508. * of lists of vertices.                                 M
  509. *                                                                            *
  510. * PARAMETERS:                                                                M
  511. *   RUOrder:     U order of surface.                                         M
  512. *   RVOrder:     V order of surface.                                         M
  513. *   LstObjList:  A list object of lists of control points.                   M
  514. *   KntObjList:  A list of knots (numeric values).                           M
  515. *                                                                            *
  516. * RETURN VALUE:                                                              M
  517. *   IPObjectStruct *: A Bspline surface object if successful, NULL otherwise.M
  518. *                                                                            *
  519. * KEYWORDS:                                                                  M
  520. *   GenBsplineSurfaceObject                                                  M
  521. *****************************************************************************/
  522. IPObjectStruct *GenBsplineSurfaceObject(RealType *RUOrder,
  523.                     RealType *RVOrder,
  524.                     IPObjectStruct *LstObjList,
  525.                     IPObjectStruct *KntObjList)
  526. {
  527.     int Len1, Len2,
  528.     UOrder = REAL_PTR_TO_INT(RUOrder),
  529.     VOrder = REAL_PTR_TO_INT(RVOrder);
  530.     char *ErrStr, Line[LINE_LEN];
  531.     IPObjectStruct
  532.     *SrfObj = GetControlMesh(LstObjList, UOrder, VOrder,
  533.                       CAGD_SBSPLINE_TYPE, &ErrStr);
  534.  
  535.     if (SrfObj == NULL) {
  536.     sprintf(Line, "SBSPLINE: Ctl mesh, %s, empty object result.\n", ErrStr);
  537.     IritPrsrFatalError(Line);
  538.     return NULL;
  539.     }
  540.  
  541.     if (!IP_IS_OLST_OBJ(KntObjList) || ListObjectLength(KntObjList) != 2) {
  542.     IPFreeObject(SrfObj);
  543.     IritPrsrFatalError("SBSPLINE: Exactly two knot vectors expected");
  544.     return NULL;
  545.     }
  546.  
  547.     if (SrfObj -> U.Srfs -> ULength < SrfObj -> U.Srfs -> UOrder ||
  548.     SrfObj -> U.Srfs -> VLength < SrfObj -> U.Srfs -> VOrder) {
  549.     IPFreeObject(SrfObj);
  550.     IritPrsrFatalError("SBSPLINE: Surface mesh length smaller than order.");
  551.     return NULL;
  552.     }
  553.  
  554.     IritFree((VoidPtr) SrfObj -> U.Srfs -> UKnotVector);
  555.     SrfObj -> U.Srfs -> UKnotVector = NULL;
  556.     IritFree((VoidPtr) SrfObj -> U.Srfs -> VKnotVector);
  557.     SrfObj -> U.Srfs -> VKnotVector = NULL;
  558.     Len1 = SrfObj -> U.Srfs -> ULength;
  559.     Len2 = SrfObj -> U.Srfs -> VLength;
  560.     if ((SrfObj -> U.Srfs -> UKnotVector =
  561.      GetKnotVector(ListObjectGet(KntObjList, 0), UOrder,
  562.                &Len1, &ErrStr)) == NULL ||
  563.     (SrfObj -> U.Srfs -> VKnotVector =
  564.      GetKnotVector(ListObjectGet(KntObjList, 1), VOrder,
  565.                &Len2, &ErrStr)) == NULL) {
  566.     IPFreeObject(SrfObj);
  567.     sprintf(Line, "SBSPLINE: Knot vectors, %s, empty object result.\n", ErrStr);
  568.     IritPrsrFatalError(Line);
  569.     return NULL;
  570.     }
  571.  
  572.     if (Len1 != SrfObj -> U.Srfs -> ULength + UOrder) {
  573.     if (Len1 == SrfObj -> U.Srfs -> ULength + UOrder + UOrder - 1)
  574.         SrfObj -> U.Srfs -> UPeriodic = TRUE;
  575.     else {
  576.         IPFreeObject(SrfObj);
  577.         IritPrsrFatalError("Wrong knot vector length");
  578.         return NULL;
  579.     }
  580.     }
  581.     if (Len2 != SrfObj -> U.Srfs -> VLength + VOrder) {
  582.     if (Len2 == SrfObj -> U.Srfs -> VLength + VOrder + VOrder - 1)
  583.         SrfObj -> U.Srfs -> VPeriodic = TRUE;
  584.     else {
  585.         IPFreeObject(SrfObj);
  586.         IritPrsrFatalError("Wrong knot vector length");
  587.         return NULL;
  588.     }
  589.     }
  590.  
  591.     return SrfObj;
  592.  
  593. }
  594.  
  595. /*****************************************************************************
  596. * DESCRIPTION:                                                               M
  597. *   Routine to create a Bspline curve geometric object defined by a list     M
  598. * of vertices.                                     M
  599. *                                                                            *
  600. * PARAMETERS:                                                                M
  601. *   ROrder:      Order of surface.                                           M
  602. *   PtObjList:   A list object of control points.                          M
  603. *   KntObjList:  A list of knots (numeric values).                           M
  604. *                                                                            *
  605. * RETURN VALUE:                                                              M
  606. *   IPObjectStruct *: A Bspline curve object if successful, NULL otherwise.  M
  607. *                                                                            *
  608. * KEYWORDS:                                                                  M
  609. *   GenBsplineCurveObject                                                    M
  610. *****************************************************************************/
  611. IPObjectStruct *GenBsplineCurveObject(RealType *ROrder,
  612.                       IPObjectStruct *PtObjList,
  613.                       IPObjectStruct *KntObjList)
  614. {
  615.     int Len,
  616.     Order = REAL_PTR_TO_INT(ROrder);
  617.     char *ErrStr, Line[LINE_LEN];
  618.     IPObjectStruct
  619.     *CrvObj = GetControlPoly(PtObjList, Order, CAGD_CBSPLINE_TYPE, &ErrStr);
  620.  
  621.     if (CrvObj == NULL) {
  622.     sprintf(Line, "CBSPLINE: Ctl polygon, %s, empty object result.\n", ErrStr);
  623.     IritPrsrFatalError(Line);
  624.     return NULL;
  625.     }
  626.  
  627.     if (!IP_IS_OLST_OBJ(KntObjList)) {
  628.     IPFreeObject( CrvObj);
  629.     IritPrsrFatalError("CBSPLINE: Exactly one knot vector expected");
  630.     return NULL;
  631.     }
  632.  
  633.     if (CrvObj -> U.Crvs -> Length < CrvObj -> U.Crvs -> Order) {
  634.     IPFreeObject(CrvObj);
  635.     IritPrsrFatalError("CBSPLINE: Curve polygon length smaller than order.");
  636.     return NULL;
  637.     }
  638.  
  639.     IritFree((VoidPtr) CrvObj -> U.Crvs -> KnotVector);
  640.     CrvObj -> U.Crvs -> KnotVector = NULL;
  641.     Len = CrvObj -> U.Crvs -> Length;
  642.     if ((CrvObj -> U.Crvs -> KnotVector =
  643.      GetKnotVector(KntObjList, Order, &Len, &ErrStr)) == NULL) {
  644.     IPFreeObject(CrvObj);
  645.     sprintf(Line, "CBSPLINE: Knot vector, %s, empty object result.\n", ErrStr);
  646.     IritPrsrFatalError(Line);
  647.     return NULL;
  648.     }
  649.  
  650.     if (Len != CrvObj -> U.Crvs -> Length + Order) {
  651.     if (Len == CrvObj -> U.Crvs -> Length + Order + Order - 1)
  652.         CrvObj -> U.Crvs -> Periodic = TRUE;
  653.     else {
  654.         IPFreeObject(CrvObj);
  655.         IritPrsrFatalError("CBSPLINE: Wrong knot vector length");
  656.         return NULL;
  657.     }
  658.     }
  659.  
  660.     return CrvObj;
  661. }
  662.  
  663. /*****************************************************************************
  664. * DESCRIPTION:                                                               M
  665. * Routine to approximate a surface of revolution by rotating the given       M
  666. * cross section along Z axes, as a cubic POLYNOMIAL surface.             M
  667. *                                                                            *
  668. * PARAMETERS:                                                                M
  669. *   Cross:    A curve torotate around the Zaxis.                             M
  670. *                                                                            *
  671. * RETURN VALUE:                                                              M
  672. *   IPObjectStruct *:  A surface of revolution by rotating Cross around Z.   M
  673. *                                                                            *
  674. * KEYWORDS:                                                                  M
  675. *   GenSURFPREVObject                                                        M
  676. *****************************************************************************/
  677. IPObjectStruct *GenSURFPREVObject(IPObjectStruct *Cross)
  678. {
  679.     if (IP_IS_CRV_OBJ(Cross)) {
  680.     if (CAGD_NUM_OF_PT_COORD(Cross -> U.Crvs -> PType) < 3) {
  681.         IritPrsrFatalError("SurfRev: cross-section perpendicular to Z. Empty object result");
  682.         return NULL;
  683.     }
  684.  
  685.     return GenSRFObject(CagdSurfaceRevPolynomialApprox(Cross -> U.Crvs));
  686.     }
  687.     else
  688.         return NULL;
  689. }
  690.  
  691. /*****************************************************************************
  692. * DESCRIPTION:                                                               M
  693. * Routine to subdivide a surface into two in specified direction (1 or 2)    M
  694. * and specified parameter value.                         M
  695. *                                                                            *
  696. * PARAMETERS:                                                                M
  697. *   SrfObj:       Surface to subdivide.                                      M
  698. *   RDir:         Direction of subdivision. Either U or V.                   M
  699. *   ParamVal:     Parameter value at which subdivision should occur.         M
  700. *                                                                            *
  701. * RETURN VALUE:                                                              M
  702. *   IPObjectStruct *:  A list object of two surface objects, result of the   M
  703. *               subdivision.                         M
  704. *                                                                            *
  705. * KEYWORDS:                                                                  M
  706. *   DivideSurfaceObject                                                      M
  707. *****************************************************************************/
  708. IPObjectStruct *DivideSurfaceObject(IPObjectStruct *SrfObj,
  709.                     RealType *RDir,
  710.                     RealType *ParamVal)
  711. {
  712.     int Dir = REAL_PTR_TO_INT(RDir);
  713.     CagdSrfStruct
  714.     *Srf = CagdSrfSubdivAtParam(SrfObj -> U.Srfs, *ParamVal, Dir);
  715.     IPObjectStruct *Srf1, *Srf2, *SrfList;
  716.  
  717.     if (Srf == NULL)
  718.     return NULL;
  719.  
  720.     Srf1 = GenSRFObject(Srf),
  721.     AttrSetObjectColor(Srf1, AttrGetObjectColor(SrfObj));
  722.     Srf2 = GenSRFObject(Srf -> Pnext),
  723.     AttrSetObjectColor(Srf2, AttrGetObjectColor(SrfObj));
  724.     Srf -> Pnext = NULL;
  725.  
  726.     SrfList = IPAllocObject("", IP_OBJ_LIST_OBJ, NULL);
  727.     ListObjectInsert(SrfList, 0, Srf1);
  728.     ListObjectInsert(SrfList, 1, Srf2);
  729.     ListObjectInsert(SrfList, 2, NULL);
  730.  
  731.     return SrfList;
  732. }
  733.  
  734. /*****************************************************************************
  735. * DESCRIPTION:                                                               M
  736. * Routine to extract a surface region in specified direction (1 or 2) and    M
  737. * specified parameter values.                             M
  738. *                                                                            *
  739. * PARAMETERS:                                                                M
  740. *   SrfObj:      Surface to extract a region from.                           M
  741. *   RDir:        Direction of region extraction. Either U or V.              M
  742. *   ParamVal1:   Parameter of beginning of region.                           M
  743. *   ParamVal2:   Parameter of end of region.                                 M
  744. *                                                                            *
  745. * RETURN VALUE:                                                              M
  746. *   IPObjectStruct *:  A region of SrfObj,                                   M
  747. *                                                                            *
  748. * KEYWORDS:                                                                  M
  749. *   RegionFromSurfaceObject                                                  M
  750. *****************************************************************************/
  751. IPObjectStruct *RegionFromSurfaceObject(IPObjectStruct *SrfObj, 
  752.                     RealType *RDir,
  753.                     RealType *ParamVal1,
  754.                     RealType *ParamVal2)
  755. {
  756.     int Dir = REAL_PTR_TO_INT(RDir);
  757.     CagdSrfStruct
  758.     *Srf = CagdSrfRegionFromSrf(SrfObj -> U.Srfs,
  759.                     *ParamVal1, *ParamVal2, Dir);
  760.  
  761.     if (Srf == NULL)
  762.     return NULL;
  763.  
  764.     SrfObj = GenSRFObject(Srf);
  765.  
  766.     return SrfObj;
  767. }
  768.  
  769. /*****************************************************************************
  770. * DESCRIPTION:                                                               M
  771. * Routine to subdivide a curve into two in specified parameter value.         M
  772. *                                                                            *
  773. * PARAMETERS:                                                                M
  774. *   CrvObj:       Curve to subdivide.                                        M
  775. *   ParamVal:     Parameter value at which subdivision should occur.         M
  776. *                                                                            *
  777. * RETURN VALUE:                                                              M
  778. *   IPObjectStruct *:  A list object of two curve objects, result of the     M
  779. *               subdivision.                         M
  780. *                                                                            *
  781. * KEYWORDS:                                                                  M
  782. *   DivideCurveObject                                                        M
  783. *****************************************************************************/
  784. IPObjectStruct *DivideCurveObject(IPObjectStruct *CrvObj, RealType *ParamVal)
  785. {
  786.     CagdCrvStruct
  787.     *Crv = CagdCrvSubdivAtParam(CrvObj -> U.Crvs, *ParamVal);
  788.     IPObjectStruct *Crv1, *Crv2, *CrvList;
  789.  
  790.     if (Crv == NULL)
  791.     return NULL;
  792.  
  793.     Crv1 = GenCRVObject(Crv);
  794.     AttrSetObjectColor(Crv1, AttrGetObjectColor(CrvObj));
  795.     Crv2 = GenCRVObject(Crv -> Pnext);
  796.     AttrSetObjectColor(Crv2, AttrGetObjectColor(CrvObj));
  797.     Crv -> Pnext = NULL;
  798.  
  799.     CrvList = IPAllocObject("", IP_OBJ_LIST_OBJ, NULL);
  800.     ListObjectInsert(CrvList, 0, Crv1);
  801.     ListObjectInsert(CrvList, 1, Crv2);
  802.     ListObjectInsert(CrvList, 2, NULL);
  803.  
  804.     return CrvList;
  805. }
  806.  
  807. /*****************************************************************************
  808. * DESCRIPTION:                                                               M
  809. * Routine to extract a curve region in specified parameter values.         M
  810. *                                                                            *
  811. * PARAMETERS:                                                                M
  812. *   CrvObj:      Curve to extract a region from.                             M
  813. *   ParamVal1:   Parameter of beginning of region.                           M
  814. *   ParamVal2:   Parameter of end of region.                                 M
  815. *                                                                            *
  816. * RETURN VALUE:                                                              M
  817. *   IPObjectStruct *:  A region of CrvObj,                                   M
  818. *                                                                            *
  819. * KEYWORDS:                                                                  M
  820. *   RegionFromCurveObject                                                    M
  821. *****************************************************************************/
  822. IPObjectStruct *RegionFromCurveObject(IPObjectStruct *CrvObj,
  823.                       RealType *ParamVal1,
  824.                       RealType *ParamVal2)
  825. {
  826.     CagdCrvStruct
  827.     *Crv = CagdCrvRegionFromCrv(CrvObj -> U.Crvs, *ParamVal1, *ParamVal2);
  828.  
  829.     if (Crv == NULL)
  830.     return NULL;
  831.  
  832.     CrvObj = GenCRVObject(Crv);
  833.  
  834.     return CrvObj;
  835. }
  836.  
  837. /*****************************************************************************
  838. * DESCRIPTION:                                                               M
  839. * Routine to refine a surface in specified direction (1 or 2) and knot       M
  840. * vector.                                     M
  841. *   If, however, Replace is non zero, KnotsObj REPLACES current vector.      M
  842. *                                                                            *
  843. * PARAMETERS:                                                                M
  844. *   SrfObj:     Surface to refine in direction RDir.                         M
  845. *   RDir:       Direction of refinement. Either U or V,                      M
  846. *   RReplace:   If TRUE KnotsObj will replace the RDir knot vector of SrfObj.M
  847. *        Otherwise, the knots in KnotsObj will be added to it.         M
  848. *   KnotsObj:   A list of knots.                                             M
  849. *                                                                            *
  850. * RETURN VALUE:                                                              M
  851. *   IPObjectStruct *:   A refined surface, or a surface with a replaced knot M
  852. *                       vector.                                              M
  853. *                                                                            *
  854. * KEYWORDS:                                                                  M
  855. *   RefineSurfaceObject                                                      M
  856. *****************************************************************************/
  857. IPObjectStruct *RefineSurfaceObject(IPObjectStruct *SrfObj,
  858.                     RealType *RDir,
  859.                     RealType *RReplace,
  860.                     IPObjectStruct *KnotsObj)
  861. {
  862.     int n,
  863.     Replace = REAL_PTR_TO_INT(RReplace),
  864.     Dir = REAL_PTR_TO_INT(RDir);
  865.     char *ErrStr, Line[LINE_LEN];
  866.     CagdRType
  867.     *t = GetKnotVector(KnotsObj, 0, &n, &ErrStr);
  868.     CagdSrfStruct *RefSrf;
  869.     IPObjectStruct *RefSrfObj;
  870.  
  871.     if (t == NULL) {
  872.     IPFreeObject(SrfObj);
  873.     sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
  874.     IritPrsrFatalError(Line);
  875.     return NULL;
  876.     }
  877.     RefSrf = CagdSrfRefineAtParams(SrfObj -> U.Srfs, Dir, Replace, t, n);
  878.     IritFree((VoidPtr) t);
  879.     if (RefSrf == NULL)
  880.     return NULL;
  881.  
  882.     RefSrfObj = GenSRFObject(RefSrf),
  883.     AttrSetObjectColor(RefSrfObj, AttrGetObjectColor(SrfObj));
  884.     return RefSrfObj;
  885. }
  886.  
  887. /*****************************************************************************
  888. * DESCRIPTION:                                                               M
  889. * Routine to refine a curve.                             M
  890. *   If, however, Replace is non zero, KnotsObj REPLACES current vector.      M
  891. *                                                                            *
  892. * PARAMETERS:                                                                M
  893. *   CrvObj:     Curve to refine.                                      M
  894. *   RReplace:   If TRUE KnotsObj will replace the knot vector of CrvObj.     M
  895. *        Otherwise, the knots in KnotsObj will be added to it.         M
  896. *   KnotsObj:   A list of knots.                                             M
  897. *                                                                            *
  898. * RETURN VALUE:                                                              M
  899. *   IPObjectStruct *:   A refined curve, or a curve with a replaced knot     M
  900. *                       vector.                                              M
  901. *                                                                            *
  902. * KEYWORDS:                                                                  M
  903. *   RefineCurveObject                                                        M
  904. *****************************************************************************/
  905. IPObjectStruct *RefineCurveObject(IPObjectStruct *CrvObj,
  906.                   RealType *RReplace,
  907.                   IPObjectStruct *KnotsObj)
  908. {
  909.     int n,
  910.     Replace = REAL_PTR_TO_INT(RReplace);
  911.     char *ErrStr, Line[LINE_LEN];
  912.     CagdRType
  913.     *t = GetKnotVector(KnotsObj, 0, &n, &ErrStr);
  914.     CagdCrvStruct *RefCrv;
  915.     IPObjectStruct *RefCrvObj;
  916.  
  917.     if (t == NULL) {
  918.     IPFreeObject(CrvObj);
  919.     sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
  920.     IritPrsrFatalError(Line);
  921.     return NULL;
  922.     }
  923.     RefCrv = CagdCrvRefineAtParams(CrvObj -> U.Crvs, Replace, t, n);
  924.     IritFree((VoidPtr) t);
  925.     if (RefCrv == NULL)
  926.     return NULL;
  927.  
  928.     RefCrvObj = GenCRVObject(RefCrv),
  929.     AttrSetObjectColor(RefCrvObj, AttrGetObjectColor(CrvObj));
  930.     return RefCrvObj;
  931. }
  932.  
  933. /*****************************************************************************
  934. * DESCRIPTION:                                                               M
  935. * Routine to evaluate surface in specified parameter values.             M
  936. *                                                                            *
  937. * PARAMETERS:                                                                M
  938. *   SrfObj:    Surface to evaluate at (u, v).                                M
  939. *   u, v:      Parameter values to evaluate at.                              M
  940. *                                                                            *
  941. * RETURN VALUE:                                                              M
  942. *   IPObjectStruct *:  A control point of the same type SrfObj has.          M
  943. *                                                                            *
  944. * KEYWORDS:                                                                  M
  945. *   EvalSurfaceObject                                                        M
  946. *****************************************************************************/
  947. IPObjectStruct *EvalSurfaceObject(IPObjectStruct *SrfObj,
  948.                   RealType *u,
  949.                   RealType *v)
  950. {
  951.     CagdRType
  952.     *Pt = CagdSrfEval(SrfObj -> U.Srfs, *u, *v);
  953.     IPObjectStruct
  954.     *CtlPtObj = GenCTLPTObject(SrfObj -> U.Srfs -> PType, Pt, NULL);
  955.  
  956.     return CtlPtObj;
  957. }
  958.  
  959. /*****************************************************************************
  960. * DESCRIPTION:                                                               M
  961. * Routine to evaluate curve in specified parameter value.             M
  962. *                                                                            *
  963. * PARAMETERS:                                                                M
  964. *   CrvObj:    Surface to evaluate at t.                                     M
  965. *   t:         Parameter value to evaluate at.                               M
  966. *                                                                            *
  967. * RETURN VALUE:                                                              M
  968. *   IPObjectStruct *:  A control point of the same type CrvObj has.          M
  969. *                                                                            *
  970. * KEYWORDS:                                                                  M
  971. *   EvalPCurveObject                                                         M
  972. *****************************************************************************/
  973. IPObjectStruct *EvalCurveObject(IPObjectStruct *CrvObj, RealType *t)
  974. {
  975.     CagdRType
  976.     *Pt = CagdCrvEval(CrvObj -> U.Crvs, *t);
  977.     IPObjectStruct
  978.     *CtlPtObj = GenCTLPTObject(CrvObj -> U.Crvs -> PType, Pt, NULL);
  979.  
  980.     return CtlPtObj;
  981. }
  982.  
  983. /*****************************************************************************
  984. * DESCRIPTION:                                                               M
  985. * Routine to compute the derivative surface in Dir of SrfObj.             M
  986. *                                                                            *
  987. * PARAMETERS:                                                                M
  988. *   SrfObj:    Surface to differentiate.                                     M
  989. *   Dir:       Direction of differentiation. Either U or V.                  M
  990. *                                                                            *
  991. * RETURN VALUE:                                                              M
  992. *   IPObjectStruct *:   A differentiated surface.                            M
  993. *                                                                            *
  994. * KEYWORDS:                                                                  M
  995. *   DeriveSurfaceObject                                                      M
  996. *****************************************************************************/
  997. IPObjectStruct *DeriveSurfaceObject(IPObjectStruct *SrfObj, RealType *Dir)
  998. {
  999.     CagdSrfStruct
  1000.     *DerivSrf = CagdSrfDerive(SrfObj -> U.Srfs, REAL_PTR_TO_INT(Dir));
  1001.     IPObjectStruct
  1002.     *DerivSrfObj = GenSRFObject(DerivSrf);
  1003.  
  1004.     return DerivSrfObj;
  1005. }
  1006.  
  1007. /*****************************************************************************
  1008. * DESCRIPTION:                                                               M
  1009. * Routine to compute the derivative curve of CrvObj.                 M
  1010. *                                                                            *
  1011. * PARAMETERS:                                                                M
  1012. *   CrvObj:    Curve to differentiate.                                       M
  1013. *                                                                            *
  1014. * RETURN VALUE:                                                              M
  1015. *   IPObjectStruct *:    A differentiated curve.                             M
  1016. *                                                                            *
  1017. * KEYWORDS:                                                                  M
  1018. *   DeriveCurveObject                                                        M
  1019. *****************************************************************************/
  1020. IPObjectStruct *DeriveCurveObject(IPObjectStruct *CrvObj)
  1021. {
  1022.     CagdCrvStruct
  1023.     *DerivCrv = CagdCrvDerive(CrvObj -> U.Crvs);
  1024.     IPObjectStruct
  1025.     *DerivCrvObj = GenCRVObject(DerivCrv);
  1026.  
  1027.     return DerivCrvObj;
  1028. }
  1029.  
  1030. /*****************************************************************************
  1031. * DESCRIPTION:                                                               M
  1032. * Routine to compute the integral curve of CrvObj.                 M
  1033. *                                                                            *
  1034. * PARAMETERS:                                                                M
  1035. *   CrvObj:    Curve to integrate.                                           M
  1036. *                                                                            *
  1037. * RETURN VALUE:                                                              M
  1038. *   IPObjectStruct *:    Integrated curve.                                   M
  1039. *                                                                            *
  1040. * KEYWORDS:                                                                  M
  1041. *   IntegrateCurveObject                                                     M
  1042. *****************************************************************************/
  1043. IPObjectStruct *IntegrateCurveObject(IPObjectStruct *CrvObj)
  1044. {
  1045.     CagdCrvStruct
  1046.     *DerivCrv = CagdCrvIntegrate(CrvObj -> U.Crvs);
  1047.     IPObjectStruct
  1048.     *DerivCrvObj = GenCRVObject(DerivCrv);
  1049.  
  1050.     return DerivCrvObj;
  1051. }
  1052.  
  1053. /*****************************************************************************
  1054. * DESCRIPTION:                                                               M
  1055. * Routine to compute the normal surface of SrfObj.                 M
  1056. *                                                                            *
  1057. * PARAMETERS:                                                                M
  1058. *   SrfObj:    Surface to compute a normal vector field for.                 M
  1059. *                                                                            *
  1060. * RETURN VALUE:                                                              M
  1061. *   IPObjectStruct *:   A vector field surface representing SrfObj's normal. M
  1062. *                                                                            *
  1063. * KEYWORDS:                                                                  M
  1064. *   SurfaceNormalObject                                                      M
  1065. *****************************************************************************/
  1066. IPObjectStruct *SurfaceNormalObject(IPObjectStruct *SrfObj)
  1067. {
  1068.     CagdSrfStruct
  1069.     *NormalSrf = SymbSrfNormalSrf(SrfObj -> U.Srfs);
  1070.     IPObjectStruct
  1071.     *NormalSrfObj = GenSRFObject(NormalSrf);
  1072.  
  1073.     return NormalSrfObj;
  1074. }
  1075.  
  1076. /*****************************************************************************
  1077. * DESCRIPTION:                                                               M
  1078. * Routine to evaluate surface's normal in specified parameter values.         M
  1079. *                                                                            *
  1080. * PARAMETERS:                                                                M
  1081. *   SrfObj:   Surface to evaluate its normal at (u, v).                      M
  1082. *   u, v:     Parameters at which to evaluate SrfObj's normal.               M
  1083. *                                                                            *
  1084. * RETURN VALUE:                                                              M
  1085. *   IPObjectStruct *:  A vector object representing the normal of SrfObj     M
  1086. *                      at (u, v).                                            M
  1087. *                                                                            *
  1088. * KEYWORDS:                                                                  M
  1089. *   NormalSurfaceObject                                                      M
  1090. *****************************************************************************/
  1091. IPObjectStruct *NormalSurfaceObject(IPObjectStruct *SrfObj,
  1092.                     RealType *u,
  1093.                     RealType *v)
  1094. {
  1095.     int i;
  1096.     RealType V[3];
  1097.     CagdVecStruct
  1098.     *Vec = CagdSrfNormal(SrfObj -> U.Srfs, *u, *v);
  1099.     IPObjectStruct *NormalObj;
  1100.  
  1101.     for (i = 0; i < 3; i++)
  1102.     V[i] = Vec -> Vec[i];
  1103.  
  1104.     NormalObj = GenVECObject(&V[0], &V[1], &V[2]);
  1105.  
  1106.     return NormalObj;
  1107. }
  1108.  
  1109. /*****************************************************************************
  1110. * DESCRIPTION:                                                               M
  1111. * Routine to evaluate surface's tangent in specified parameter value and dir.M
  1112. *                                                                            *
  1113. * PARAMETERS:                                                                M
  1114. *   SrfObj:   Surface to evaluate its tangent at (u, v).                     M
  1115. *   RDir:     Direction of tangent, Either U or V.                           M
  1116. *   u, v:     Parameters at which to evaluate SrfObj's tangent.              M
  1117. *                                                                            *
  1118. * RETURN VALUE:                                                              M
  1119. *   IPObjectStruct *:   A vector object representing the tangent of SrfObj   M
  1120. *                       at (u, v) in direction RDir.                         M
  1121. *                                                                            *
  1122. * KEYWORDS:                                                                  M
  1123. *   TangentSurfaceObject                                                     M
  1124. *****************************************************************************/
  1125. IPObjectStruct *TangentSurfaceObject(IPObjectStruct *SrfObj,
  1126.                      RealType *RDir,
  1127.                      RealType *u,
  1128.                      RealType *v)
  1129. {
  1130.     int i,
  1131.     Dir = REAL_PTR_TO_INT(RDir);
  1132.     RealType V[3];
  1133.     CagdVecStruct
  1134.     *Vec = CagdSrfTangent(SrfObj -> U.Srfs, *u, *v, Dir);
  1135.     IPObjectStruct *TangentObj;
  1136.  
  1137.     for (i = 0; i < 3; i++)
  1138.     V[i] = Vec -> Vec[i];
  1139.  
  1140.     TangentObj = GenVECObject(&V[0], &V[1], &V[2]);
  1141.  
  1142.     return TangentObj;
  1143. }
  1144.  
  1145. /*****************************************************************************
  1146. * DESCRIPTION:                                                               M
  1147. * Routine to evaluate curve's tangent in specified parameter value.         M
  1148. *                                                                            *
  1149. * PARAMETERS:                                                                M
  1150. *   CrvObj:    Curve to evaluate its tangent at t.                           M
  1151. *   t:         Parameter to evaluate CrvObj at.                              M
  1152. *                                                                            *
  1153. * RETURN VALUE:                                                              M
  1154. *   IPObjectStruct *:   A vector object representing the tangent of CrvObj.  M
  1155. *                                                                            *
  1156. * KEYWORDS:                                                                  M
  1157. *   TangentCurveObject                                                       M
  1158. *                                                                            M
  1159. *****************************************************************************/
  1160. IPObjectStruct *TangentCurveObject(IPObjectStruct *CrvObj, RealType *t)
  1161. {
  1162.     int i;
  1163.     RealType V[3];
  1164.     CagdVecStruct
  1165.     *Vec = CagdCrvTangent(CrvObj -> U.Crvs, *t);
  1166.     IPObjectStruct *TangentObj;
  1167.  
  1168.     for (i = 0; i < 3; i++)
  1169.     V[i] = Vec -> Vec[i];
  1170.  
  1171.     TangentObj = GenVECObject(&V[0], &V[1], &V[2]);
  1172.  
  1173.     return TangentObj;
  1174. }
  1175.  
  1176. /*****************************************************************************
  1177. * DESCRIPTION:                                                               M
  1178. * Routine to extract an isoparametric curve out of a surface.             M
  1179. *                                                                            *
  1180. * PARAMETERS:                                                                M
  1181. *   SrfObj:     Surface to extract an isoparametric curve from.              M
  1182. *   RDir:       Direction of extraction. Either U or V.                      M
  1183. *   ParamVal:   Parameter value of isoparametric curve.                      M
  1184. *                                                                            *
  1185. * RETURN VALUE:                                                              M
  1186. *   IPObjectStruct *:  A curve object which is an isoparametric curve of     M
  1187. *                      SrfObj.                                               M
  1188. *                                                                            *
  1189. * KEYWORDS:                                                                  M
  1190. *   CurveFromSurface                                                         M
  1191. *****************************************************************************/
  1192. IPObjectStruct *CurveFromSurface(IPObjectStruct *SrfObj,
  1193.                  RealType *RDir,
  1194.                  RealType *ParamVal)
  1195. {
  1196.     int Dir = REAL_PTR_TO_INT(RDir);
  1197.     CagdCrvStruct
  1198.     *Crv = CagdCrvFromSrf(SrfObj -> U.Srfs, *ParamVal, Dir);
  1199.     IPObjectStruct *CrvObj;
  1200.  
  1201.     if (Crv == NULL)
  1202.     return NULL;
  1203.  
  1204.     CrvObj = GenCRVObject(Crv);
  1205.  
  1206.     return CrvObj;
  1207. }
  1208.  
  1209. /*****************************************************************************
  1210. * DESCRIPTION:                                                               M
  1211. * Routine to extract an isoparametric curve out of a surface mesh.         M
  1212. *                                                                            *
  1213. * PARAMETERS:                                                                M
  1214. *   SrfObj:     Surface to extract an isoparametric curve from itsmesh.      M
  1215. *   RDir:       Direction of extraction. Either U or V.                      M
  1216. *   RIndex:     Index into SrfObj's mesh.                                    M
  1217. *                                                                            *
  1218. * RETURN VALUE:                                                              M
  1219. *   IPObjectStruct *:  A curve object which is not necessarily in SrfObj.    M
  1220. *                                                                            *
  1221. * KEYWORDS:                                                                  M
  1222. *   CurveFromSrfMesh                                                         M
  1223. *****************************************************************************/
  1224. IPObjectStruct *CurveFromSrfMesh(IPObjectStruct *SrfObj,
  1225.                  RealType *RDir,
  1226.                  RealType *RIndex)
  1227. {
  1228.     int Dir = REAL_PTR_TO_INT(RDir),
  1229.     Index = REAL_PTR_TO_INT(RIndex);
  1230.     CagdCrvStruct
  1231.     *Crv = CagdCrvFromMesh(SrfObj -> U.Srfs, Index, Dir);
  1232.     IPObjectStruct *CrvObj;
  1233.  
  1234.     if (Crv == NULL)
  1235.     return NULL;
  1236.  
  1237.     CrvObj = GenCRVObject(Crv);
  1238.  
  1239.     return CrvObj;
  1240. }
  1241.